/**
 * 
 */
package loansManagement;

import hibernateUtils.HibernateUtil;

import java.io.Serializable;
import java.util.Calendar;
import java.util.GregorianCalendar;

import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.Column;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.Session;

import daos.DAOs;





import exceptions.BadParametersException;
import exceptions.ChildLoanException;
import exceptions.LentMediaException;

import main.Constraints;
import mediasManagement.Exemplary;
import mediasManagement.Media;
import subscribersManagement.Subscriber;

/** 
 * @author virgil
 */

@Entity
@AssociationOverride(name = "pk.subscriber",
			joinColumns=@JoinColumn(name="SUBSCRIBER_ID"))
@AttributeOverride(name = "pk.exemplary",
			column=@Column(name="EXEMPLARY_ID"))
public class Loan {

	/**
	 * @uml.property  name="subscriber"
	 * @uml.associationEnd  inverse="currentloans:subscribersManagement.Subscriber"
	 */
	
	
	public Loan(Media media, Subscriber lender) throws BadParametersException, LentMediaException, ChildLoanException {
		// TODO Auto-generated constructor stub
		if ((media == null) || (lender == null))
			throw new BadParametersException();
		this.pk = new LoanId();
		this.media = media;
		setLender(lender);
		Calendar rDate = new GregorianCalendar();
		rDate.add(Calendar.MONTH, Constraints.loanDELAY);
		this.returnDate = rDate;
	
		//retrieve a exemplary of the media wich can be lent
		setExemplary(media.lend(this));
		
		//update the loans of the suscriber if he can lend the media
		lender.lend(this);
	
	}
	
	public Loan (){
		this.pk=new LoanId();
	}

	
	/**
	 * @uml.property  name="exemplary"
	 * @uml.associationEnd  inverse="currentLoan:mediasManagement.Exemplary"
	 */
	
	
	/**
	 * Getter of the property <tt>exemplary</tt>
	 * @return  Returns the exemplary.
	 * @uml.property  name="exemplary"
	 */
	@Transient
	public Exemplary getExemplary() {
		return getPk().getExemplary();
	}

	/**
	 * Setter of the property <tt>exemplary</tt>
	 * @param exemplary  The exemplary to set.
	 * @uml.property  name="exemplary"
	 */
	public void setExemplary(Exemplary exemplary) {
		getPk().setExemplary(exemplary);
	}

	/**
	 * Getter of the property <tt>returnDate</tt>
	 * @return  Returns the returnDate.
	 * @uml.property  name="returnDate"
	 */
	
	public Calendar getReturnDate() {
		return returnDate;
	}

	

	/**
	 * @uml.property  name="returnDate"
	 */
	
	private Calendar returnDate;

	/**
	 * Setter of the property <tt>returnDate</tt>
	 * @param returnDate  The returnDate to set.
	 * @uml.property  name="returnDate"
	 */
	public void setReturnDate(Calendar returnDate) {
		this.returnDate = returnDate;
	}

	/**
	 * @uml.property  name="media"
	 * @uml.associationEnd  inverse="loans:mediasManagement.Media"
	 */
	@Transient
	private Media media;

	/**
	 * Getter of the property <tt>media</tt>
	 * @return  Returns the media.
	 * @uml.property  name="media"
	 */
	
	public Media getMedia() {
		return media;
	}

	/**
	 * Setter of the property <tt>media</tt>
	 * @param media  The media to set.
	 * @uml.property  name="media"
	 */
	public void setMedia(Media media) {
		this.media = media;
	}

	
	
 public String toString(){
	 
	return getLender().toString()+" lend "+getExemplary().toString()+" .A Rendre le\n"+
			returnDate.getTime();
	 
 }

 //About primary Key
/**
 * @uml.property  name="loanId"
 * @uml.associationEnd  inverse="loan:loansManagement.LoanId"
 */
 @EmbeddedId
private LoanId pk;



/**
 * Getter of the property <tt>loanId</tt>
 * @return  Returns the loanId.
 * @uml.property  name="loanId"
 */
public LoanId getPk() {
	return pk;
}

/**
 * Setter of the property <tt>loanId</tt>
 * @param loanId  The loanId to set.
 * @uml.property  name="loanId"
 */
public void setPk(LoanId pk) {
	this.pk = pk;
}
	
public boolean equals(Object o) {
	if (this == o)
		return true;
	if (o == null || getClass() != o.getClass())
		return false;

	Loan that = (Loan) o;

	if (getPk() != null ? !getPk().equals(that.getPk())
			: that.getPk() != null)
		return false;

	return true;
}

public int hashCode() {
	return (getPk() != null ? getPk().hashCode() : 0);
}


//to update a loan when a media is return
/**
 * @uml.property  name="isReturn"
 */
private boolean isReturn = false;

/**
 * Getter of the property <tt>isReturn</tt>
 * @return  Returns the isReturn.
 * @uml.property  name="isReturn"
 */
public boolean isIsReturn() {
	return isReturn;
}

/**
 * Setter of the property <tt>isReturn</tt>
 * @param isReturn  The isReturn to set.
 * @uml.property  name="isReturn"
 */
public void setIsReturn(boolean isReturn) {
	this.isReturn = isReturn;
}

/**
 * Getter of the property <tt>subscriber</tt>
 * @return   Returns the subscriber.
 * @uml.property   name="subscriber"
 */
@Transient
public Subscriber getLender() {
	return getPk().getSubscriber();
}

/**
 * Setter of the property <tt>subscriber</tt>
 * @param subscriber   The subscriber to set.
 * @uml.property   name="subscriber"
 */
public void setLender(Subscriber lender) {
	getPk().setSubscriber(lender);
}



/**
 * @uml.property  name="lender"
 * @uml.associationEnd  inverse="currentloans:subscribersManagement.Subscriber"
 */


}
